package br.ufrj.dcc.ad.systems;

import java.util.List;

import br.ufrj.dcc.ad.args.ParametrosSimulacao;
import br.ufrj.dcc.ad.enums.ServerType;
import br.ufrj.dcc.ad.interfaces.IServidor;

public class Servidor implements IServidor{
	
	private Cliente consumidor;
	private List<Fila> filasDePrioridade;
	/**
	 * Inicializa o servidor.
	 * @param filasDePrioridade As filas em ordem de prioridade de atendimento no servidor.
	 */
	public Servidor(List<Fila> filasDePrioridade) {
		this.filasDePrioridade = filasDePrioridade;
	}

	@Override
	public double trabalhaCargaAtual(double tempoAtual,double tempoProximoEvento) {
		double deslocamentoTempo = 0.0;
		if(ParametrosSimulacao.getTipoServidor() == ServerType.CONTINUO){
			//Para execução com continuidade.
			if(tempoProximoEvento >= tempoAtual &&
			   tempoProximoEvento <= (tempoAtual + consumidor.getTempoConsumoRestante())) {
				deslocamentoTempo = (tempoProximoEvento - tempoAtual);
				consumidor.setTempoConsumoRestante(consumidor.getTempoConsumoRestante() - deslocamentoTempo);
			}else {
				deslocamentoTempo = consumidor.getTempoConsumoRestante();
				consumidor.setTempoConsumoRestante(0.0);
			}
			consumidor.addTempoVaoServidor(consumidor.getTipoCliente(), 0.0);
		}else if(ParametrosSimulacao.getTipoServidor() == ServerType.NCONTINUO){
			//Para execução sem continuidade.
			deslocamentoTempo = (tempoProximoEvento - tempoAtual);
			//Se não há eventos entre o tempo de consumo ou o tempo é suficiente para ocorrer todo o consumo,consome... 
			if(!(tempoProximoEvento >= tempoAtual &&
			   tempoProximoEvento <= (tempoAtual + consumidor.getTempoConsumoRestante())) || 
			   (tempoAtual - consumidor.getTempoUltimaEntradaServidor()) >= consumidor.getTempoConsumoRestante()) {
					deslocamentoTempo = consumidor.getTempoConsumoRestante() - (tempoAtual - consumidor.getTempoUltimaEntradaServidor());
					consumidor.setTempoConsumoRestante(0.0);
					consumidor.addTempoVaoServidor(consumidor.getTipoCliente(),0.0);
			}
		}
		return deslocamentoTempo;
	}
	
	@Override
	public boolean isOcupado() {
		return consumidor != null;
	}

	@Override
	public Cliente getAndRemoveProximoCliente() {
		Cliente proximoCliente = null; 
		for(Fila fila:filasDePrioridade) {
			if (!fila.isEmpty()){
				return fila.getAndRemoveNext();
			}
		}
		return proximoCliente;
	}
	
	@Override
	public void setConsumidor(Cliente cliente) {
		this.consumidor = cliente;
	}

	public Cliente getConsumidor() {
		return consumidor;
	}
	
	public List<Fila> getFilasDePrioridade() {
		return filasDePrioridade;
	}

	public void setFilasDePrioridade(List<Fila> filasDePrioridade) {
		this.filasDePrioridade = filasDePrioridade;
	}
	
	public void resetaServidor() {
		this.consumidor = null;
		for(Fila fila : filasDePrioridade) {
			fila.resetGeradorServico();
			fila.clear();
		}
	}
	
	public double geraAmostra(int tipoCliente) {
		return filasDePrioridade.get(tipoCliente).getGeradorServico().geraAmostra();
	}
}
